package api

import (
	"encoding/json"
	"epg-mc/database/table/config"
	"epg/api"
	"epg/log"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"

	"fmt"

	"github.com/labstack/echo"
)

var base *Base

//Base template data
type Base struct {
	data map[string]interface{}
}

func init() {
	base = &Base{data: make(map[string]interface{})}
	base.data["title"] = config.GetValue(config.SiteTitle)
	base.data["uname"] = ""
}

//Index url:/admin/api/index
func Index(c echo.Context) error {
	base.data["uname"] = c.Get("uname")
	_hosts := config.GetValue(config.NodeHostsAPI)
	hosts := strings.Split(_hosts, ",")
	data := make([]api.Reply, 0, 6)
	for _, v := range hosts {
		url := fmt.Sprintf("http://%s/health", v)
		reply := getReply(url, nil)
		reply.Host = v
		data = append(data, *reply)

	}
	base.data["Data"] = data
	//datacenter
	_dc := config.GetValue(config.DataCenters)
	dc := strings.Split(_dc, ",")
	base.data["Datacenter"] = dc

	err := c.Render(http.StatusOK, "api/index.html", base.data)
	if err != nil {
		c.Error(err)
	}
	return err
}

//SyncPriv sync priv
func SyncPriv(c echo.Context) error {
	base.data["uname"] = c.Get("uname")
	//GET
	if c.Request().Method() == "GET" {
		err := c.Render(http.StatusOK, "api/syncpriv.html", base.data)
		if err != nil {
			c.Error(err)
		}
		return err
	}
	data := syncPriv()
	err := c.JSON(http.StatusOK, data)
	if err != nil {
		c.Error(err)
	}
	return err
}

//SwitchDC switch datacenter
//method: POST
func SwitchDC(c echo.Context) error {
	var err error
	host := c.FormValue("host")
	dc := c.FormValue("dc")
	url := fmt.Sprintf("http://%s/switch_datacenter&dc=%s", host, dc)
	reply := getReply(url, nil)
	reply.Host = host

	err = c.JSON(http.StatusOK, reply)
	if err != nil {
		c.Error(err)
		return err
	}
	return err
}

func Nodes(c echo.Context) error {
	base.data["uname"] = c.Get("uname")
	base.data["data"] = config.FindByKey(config.ErrorLogAPI)
	err := c.Render(http.StatusOK, "api/nodes.html", base.data)
	if err != nil {
		c.Error(err)
	}
	return err
}

func getReply(url string, data url.Values) (reply *api.Reply) {
	reply = &api.Reply{}
	resp, err := http.PostForm(url, data)
	if err != nil {
		reply.Status = api.StatusClientErr
		reply.Msg = err.Error()
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		reply.Status = api.StatusClientErr
		reply.Msg = err.Error()
		return
	}

	if err := json.Unmarshal(body, reply); err != nil {
		log.Error(err)
		reply = &api.Reply{Status: api.StatusClientErr, Msg: err.Error(), Time: int64(0)}
	} else {
		reply = &api.Reply{Status: reply.Status, Time: reply.Time, Msg: reply.Msg}
	}
	return
}

func SyncPrivAPI(c echo.Context) error {
	apiKey := c.FormValue("api_key")
	_apiKey := config.GetValue(config.DBPrivAPI)
	if apiKey == "" || apiKey != _apiKey {
		err := c.JSON(http.StatusForbidden, "forbidden")
		if err != nil {
			c.Error(err)
		}
		return err
	}

	data := syncPriv()
	err := c.JSON(http.StatusOK, data)
	if err != nil {
		c.Error(err)
	}
	return err
}

func syncPriv() [][]string {
	_hosts := config.GetValue(config.NodeHostsAPI)
	hosts := strings.Split(_hosts, ",")
	//host, status, time, message
	var timeFunc = func(ts int64) string {
		return time.Unix(ts, 0).Format("2006-01-02 03:04:05 PM")
	}
	data := make([][]string, 0, 8)
	for _, v := range hosts {
		url := fmt.Sprintf("http://%s/sync_priv", v)
		reply := getReply(url, nil)
		reply.Host = v
		data = append(data, []string{v, fmt.Sprint(reply.Status), timeFunc(reply.Time), reply.Msg})
	}
	return data
}
